package myutil

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

// SizeOfDir 计算目录总大小（递归）
func SizeOfDir(file string) int64 {
	var total int64 = 0
	err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			total += info.Size()
		}
		return nil
	})

	if err != nil {
		panic(err.Error())
	}
	return total
}

// GetSaveFilePath 获取文件保存路径，自动处理目录创建和文件名冲突
func GetSaveFilePath(subPath string, filename string) (string, error) {
	filename = filepath.Base(filename)

	downloadsDir, err := GetDownloadsDirectory()
	if err != nil {
		return "", err
	}

	targetDir := filepath.Join(downloadsDir, subPath)

	// 确保目录存在
	if err := os.MkdirAll(targetDir, 0755); err != nil {
		return "", fmt.Errorf("无法创建目录: %w", err)
	}

	// 检查文件是否存在，不存在则直接返回
	initialPath := filepath.Join(targetDir, filename)
	if _, err := os.Stat(initialPath); os.IsNotExist(err) {
		return initialPath, nil
	} else if err != nil {
		return "", fmt.Errorf("检查文件存在性失败: %w", err)
	}

	// 处理文件重名情况
	return generateIncrementedPath(targetDir, filename)
}

// 获取系统下载目录
func GetDownloadsDirectory() (string, error) {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return "", fmt.Errorf("无法获取用户主目录: %w", err)
	}
	// 尝试常见的下载目录位置
	downloadsDirs := []string{
		filepath.Join(homeDir, "Downloads"),
		filepath.Join(homeDir, "下载"),
	}

	for _, dir := range downloadsDirs {
		if info, err := os.Stat(dir); err == nil && info.IsDir() {
			return dir, nil
		}
	}
	// 如果找不到特定的下载目录，返回主目录
	return homeDir, nil
}

// 生成自动递增的文件名路径
func generateIncrementedPath(dir, originalName string) (string, error) {
	baseName, extension := splitFileName(originalName)
	counter := 1

	for {
		newName := fmt.Sprintf("%s(%d)%s", baseName, counter, extension)
		path := filepath.Join(dir, newName)

		if _, err := os.Stat(path); os.IsNotExist(err) {
			return path, nil
		} else if err != nil {
			return "", fmt.Errorf("检查文件存在性失败: %w", err)
		}

		counter++
	}
}

// 分割文件名和扩展名
func splitFileName(filename string) (string, string) {
	ext := filepath.Ext(filename)
	return strings.TrimSuffix(filename, ext), ext
}

// FileChecksum 计算文件的SHA-256哈希
func FileChecksum(file *os.File) (string, error) {
	hash := sha256.New()
	if _, err := io.Copy(hash, file); err != nil {
		return "", err
	}
	return hex.EncodeToString(hash.Sum(nil)), nil
}

// FormatSize 格式化文件大小为字符串
func FormatSize(bytes int64) string {
	units := []string{"B", "KB", "MB", "GB", "TB"}
	index := 0
	size := float64(bytes)

	for size >= 1024 && index < len(units)-1 {
		size /= 1024
		index++
	}
	return fmt.Sprintf("%.2f %s", size, units[index])
}

// IncrementSuffixNumber 处理字符串，如果以 (数字) 结尾，则数字加1，否则添加 (1)
func IncrementSuffixNumber(s string, isSpace bool) string {
	// 定义正则表达式匹配以 (数字) 结尾的字符串
	re := regexp.MustCompile(`^(.*)\s?\((\d+)\)$`)

	var separator = func() string {
		if isSpace {
			return " "
		} else {
			return ""
		}
	}()

	// 检查字符串是否匹配正则表达式
	matches := re.FindStringSubmatch(s)
	if len(matches) == 3 {
		// 提取前缀和数字部分
		prefix := matches[1]
		numStr := matches[2]
		// 将数字字符串转换为整数
		num, _ := strconv.Atoi(numStr)
		// 数字加1后重新拼接字符串
		return fmt.Sprintf("%s%s(%d)", strings.TrimSpace(prefix), separator, num+1)
	} else {
		// 如果不匹配，则添加 (1)
		return strings.TrimSpace(s) + separator + "(1)"
	}
}
